package cn.chiship.sdk.core.useragent;

import cn.chiship.sdk.core.util.StringUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 操作系统
 *
 * @author lj
 */
public enum OperatingSystem {

	WINDOWS(Manufacturer.MICROSOFT, null, 1, "Windows", new String[] { "Windows" },
			new String[] { "Palm", "ggpht.com" }, DeviceType.COMPUTER, null), WINDOWS_10(Manufacturer.MICROSOFT,
					WINDOWS, 24, "Windows 10", new String[] { "Windows NT 6.4", "Windows NT 10" }, null,
					DeviceType.COMPUTER, null), WINDOWS_81(Manufacturer.MICROSOFT, WINDOWS, 23, "Windows 8.1",
							new String[] { "Windows NT 6.3" }, null, DeviceType.COMPUTER, null), WINDOWS_8(
									Manufacturer.MICROSOFT, WINDOWS, 22, "Windows 8", new String[] { "Windows NT 6.2" },
									new String[] { "Xbox", "Xbox One" }, DeviceType.COMPUTER,
									null), WINDOWS_7(Manufacturer.MICROSOFT, WINDOWS, 21, "Windows 7",
											new String[] { "Windows NT 6.1" }, new String[] { "Xbox", "Xbox One" },
											DeviceType.COMPUTER, null), WINDOWS_VISTA(Manufacturer.MICROSOFT, WINDOWS,
													20, "Windows Vista", new String[] { "Windows NT 6" },
													new String[] { "Xbox", "Xbox One" }, DeviceType.COMPUTER,
													null), WINDOWS_2000(Manufacturer.MICROSOFT, WINDOWS, 15,
															"Windows 2000", new String[] { "Windows NT 5.0" }, null,
															DeviceType.COMPUTER,
															null), WINDOWS_XP(Manufacturer.MICROSOFT, WINDOWS, 10,
																	"Windows XP", new String[] { "Windows NT 5" },
																	new String[] { "ggpht.com" }, DeviceType.COMPUTER,
																	null), WINDOWS_10_MOBILE(Manufacturer.MICROSOFT,
																			WINDOWS, 54, "Windows 10 Mobile",
																			new String[] { "Windows Phone 10" }, null,
																			DeviceType.MOBILE, null), WINDOWS_PHONE8_1(
																					Manufacturer.MICROSOFT, WINDOWS, 53,
																					"Windows Phone 8.1",
																					new String[] {
																							"Windows Phone 8.1" },
																					null, DeviceType.MOBILE,
																					null), WINDOWS_PHONE8(
																							Manufacturer.MICROSOFT,
																							WINDOWS, 52,
																							"Windows Phone 8",
																							new String[] {
																									"Windows Phone 8" },
																							null, DeviceType.MOBILE,
																							null), WINDOWS_MOBILE7(
																									Manufacturer.MICROSOFT,
																									WINDOWS, 51,
																									"Windows Phone 7",
																									new String[] {
																											"Windows Phone OS 7" },
																									null,
																									DeviceType.MOBILE,
																									null), WINDOWS_MOBILE(
																											Manufacturer.MICROSOFT,
																											WINDOWS, 50,
																											"Windows Mobile",
																											new String[] {
																													"Windows CE" },
																											null,
																											DeviceType.MOBILE,
																											null), WINDOWS_98(
																													Manufacturer.MICROSOFT,
																													WINDOWS,
																													5,
																													"Windows 98",
																													new String[] {
																															"Windows 98",
																															"Win98" },
																													new String[] {
																															"Palm" },
																													DeviceType.COMPUTER,
																													null), XBOX_OS(
																															Manufacturer.MICROSOFT,
																															WINDOWS,
																															62,
																															"Xbox OS",
																															new String[] {
																																	"xbox" },
																															new String[0],
																															DeviceType.GAME_CONSOLE,
																															null), ANDROID(
																																	Manufacturer.GOOGLE,
																																	null,
																																	0,
																																	"Android",
																																	new String[] {
																																			"Android" },
																																	new String[] {
																																			"Ubuntu" },
																																	DeviceType.MOBILE,
																																	null), ANDROID8(
																																			Manufacturer.GOOGLE,
																																			ANDROID,
																																			8,
																																			"Android 8.x",
																																			new String[] {
																																					"Android 8",
																																					"Android-8" },
																																			new String[] {
																																					"glass" },
																																			DeviceType.MOBILE,
																																			null), ANDROID8_TABLET(
																																					Manufacturer.GOOGLE,
																																					ANDROID8,
																																					80,
																																					"Android 8.x Tablet",
																																					new String[] {
																																							"Android 8",
																																							"Android-8" },
																																					new String[] {
																																							"mobile",
																																							"glass" },
																																					DeviceType.TABLET,
																																					null), ANDROID7(
																																							Manufacturer.GOOGLE,
																																							ANDROID,
																																							7,
																																							"Android 7.x",
																																							new String[] {
																																									"Android 7",
																																									"Android-7" },
																																							new String[] {
																																									"glass" },
																																							DeviceType.MOBILE,
																																							null), ANDROID7_TABLET(
																																									Manufacturer.GOOGLE,
																																									ANDROID7,
																																									70,
																																									"Android 7.x Tablet",
																																									new String[] {
																																											"Android 7",
																																											"Android-7" },
																																									new String[] {
																																											"mobile",
																																											"glass" },
																																									DeviceType.TABLET,
																																									null), ANDROID6(
																																											Manufacturer.GOOGLE,
																																											ANDROID,
																																											6,
																																											"Android 6.x",
																																											new String[] {
																																													"Android 6",
																																													"Android-6" },
																																											new String[] {
																																													"glass" },
																																											DeviceType.MOBILE,
																																											null), ANDROID6_TABLET(
																																													Manufacturer.GOOGLE,
																																													ANDROID6,
																																													60,
																																													"Android 6.x Tablet",
																																													new String[] {
																																															"Android 6",
																																															"Android-6" },
																																													new String[] {
																																															"mobile",
																																															"glass" },
																																													DeviceType.TABLET,
																																													null), ANDROID5(
																																															Manufacturer.GOOGLE,
																																															ANDROID,
																																															5,
																																															"Android 5.x",
																																															new String[] {
																																																	"Android 5",
																																																	"Android-5" },
																																															new String[] {
																																																	"glass" },
																																															DeviceType.MOBILE,
																																															null), ANDROID5_TABLET(
																																																	Manufacturer.GOOGLE,
																																																	ANDROID5,
																																																	50,
																																																	"Android 5.x Tablet",
																																																	new String[] {
																																																			"Android 5",
																																																			"Android-5" },
																																																	new String[] {
																																																			"mobile",
																																																			"glass" },
																																																	DeviceType.TABLET,
																																																	null), ANDROID4(
																																																			Manufacturer.GOOGLE,
																																																			ANDROID,
																																																			4,
																																																			"Android 4.x",
																																																			new String[] {
																																																					"Android 4",
																																																					"Android-4" },
																																																			new String[] {
																																																					"glass",
																																																					"ubuntu" },
																																																			DeviceType.MOBILE,
																																																			null), ANDROID4_TABLET(
																																																					Manufacturer.GOOGLE,
																																																					ANDROID4,
																																																					40,
																																																					"Android 4.x Tablet",
																																																					new String[] {
																																																							"Android 4",
																																																							"Android-4" },
																																																					new String[] {
																																																							"mobile",
																																																							"glass",
																																																							"ubuntu" },
																																																					DeviceType.TABLET,
																																																					null), ANDROID4_WEARABLE(
																																																							Manufacturer.GOOGLE,
																																																							ANDROID,
																																																							400,
																																																							"Android 4.x",
																																																							new String[] {
																																																									"Android 4" },
																																																							new String[] {
																																																									"ubuntu" },
																																																							DeviceType.WEARABLE,
																																																							null), ANDROID3_TABLET(
																																																									Manufacturer.GOOGLE,
																																																									ANDROID,
																																																									30,
																																																									"Android 3.x Tablet",
																																																									new String[] {
																																																											"Android 3" },
																																																									null,
																																																									DeviceType.TABLET,
																																																									null), ANDROID2(
																																																											Manufacturer.GOOGLE,
																																																											ANDROID,
																																																											2,
																																																											"Android 2.x",
																																																											new String[] {
																																																													"Android 2" },
																																																											null,
																																																											DeviceType.MOBILE,
																																																											null), ANDROID2_TABLET(
																																																													Manufacturer.GOOGLE,
																																																													ANDROID2,
																																																													20,
																																																													"Android 2.x Tablet",
																																																													new String[] {
																																																															"Kindle Fire",
																																																															"GT-P1000",
																																																															"SCH-I800" },
																																																													null,
																																																													DeviceType.TABLET,
																																																													null), ANDROID1(
																																																															Manufacturer.GOOGLE,
																																																															ANDROID,
																																																															1,
																																																															"Android 1.x",
																																																															new String[] {
																																																																	"Android 1" },
																																																															null,
																																																															DeviceType.MOBILE,
																																																															null), ANDROID_MOBILE(
																																																																	Manufacturer.GOOGLE,
																																																																	ANDROID,
																																																																	11,
																																																																	"Android Mobile",
																																																																	new String[] {
																																																																			"Mobile" },
																																																																	new String[] {
																																																																			"ubuntu" },
																																																																	DeviceType.MOBILE,
																																																																	null), ANDROID_TABLET(
																																																																			Manufacturer.GOOGLE,
																																																																			ANDROID,
																																																																			12,
																																																																			"Android Tablet",
																																																																			new String[] {
																																																																					"Tablet" },
																																																																			null,
																																																																			DeviceType.TABLET,
																																																																			null), CHROME_OS(
																																																																					Manufacturer.GOOGLE,
																																																																					null,
																																																																					1000,
																																																																					"Chrome OS",
																																																																					new String[] {
																																																																							"CrOS" },
																																																																					null,
																																																																					DeviceType.COMPUTER,
																																																																					null), WEBOS(
																																																																							Manufacturer.HP,
																																																																							null,
																																																																							11,
																																																																							"WebOS",
																																																																							new String[] {
																																																																									"webOS" },
																																																																							null,
																																																																							DeviceType.MOBILE,
																																																																							null), PALM(
																																																																									Manufacturer.HP,
																																																																									null,
																																																																									10,
																																																																									"PalmOS",
																																																																									new String[] {
																																																																											"Palm" },
																																																																									null,
																																																																									DeviceType.MOBILE,
																																																																									null), MEEGO(
																																																																											Manufacturer.NOKIA,
																																																																											null,
																																																																											3,
																																																																											"MeeGo",
																																																																											new String[] {
																																																																													"MeeGo" },
																																																																											null,
																																																																											DeviceType.MOBILE,
																																																																											null), IOS(
																																																																													Manufacturer.APPLE,
																																																																													null,
																																																																													2,
																																																																													"iOS",
																																																																													new String[] {
																																																																															"iPhone",
																																																																															"like Mac OS X" },
																																																																													null,
																																																																													DeviceType.MOBILE,
																																																																													null), iOS11_IPHONE(
																																																																															Manufacturer.APPLE,
																																																																															IOS,
																																																																															92,
																																																																															"iOS 11 (iPhone)",
																																																																															new String[] {
																																																																																	"iPhone OS 11" },
																																																																															null,
																																																																															DeviceType.MOBILE,
																																																																															null), iOS10_IPHONE(
																																																																																	Manufacturer.APPLE,
																																																																																	IOS,
																																																																																	91,
																																																																																	"iOS 10 (iPhone)",
																																																																																	new String[] {
																																																																																			"iPhone OS 10" },
																																																																																	null,
																																																																																	DeviceType.MOBILE,
																																																																																	null), iOS9_IPHONE(
																																																																																			Manufacturer.APPLE,
																																																																																			IOS,
																																																																																			90,
																																																																																			"iOS 9 (iPhone)",
																																																																																			new String[] {
																																																																																					"iPhone OS 9" },
																																																																																			null,
																																																																																			DeviceType.MOBILE,
																																																																																			null), iOS8_4_IPHONE(
																																																																																					Manufacturer.APPLE,
																																																																																					IOS,
																																																																																					49,
																																																																																					"iOS 8.4 (iPhone)",
																																																																																					new String[] {
																																																																																							"iPhone OS 8_4" },
																																																																																					null,
																																																																																					DeviceType.MOBILE,
																																																																																					null), iOS8_3_IPHONE(
																																																																																							Manufacturer.APPLE,
																																																																																							IOS,
																																																																																							48,
																																																																																							"iOS 8.3 (iPhone)",
																																																																																							new String[] {
																																																																																									"iPhone OS 8_3" },
																																																																																							null,
																																																																																							DeviceType.MOBILE,
																																																																																							null), iOS8_2_IPHONE(
																																																																																									Manufacturer.APPLE,
																																																																																									IOS,
																																																																																									47,
																																																																																									"iOS 8.2 (iPhone)",
																																																																																									new String[] {
																																																																																											"iPhone OS 8_2" },
																																																																																									null,
																																																																																									DeviceType.MOBILE,
																																																																																									null), iOS8_1_IPHONE(
																																																																																											Manufacturer.APPLE,
																																																																																											IOS,
																																																																																											46,
																																																																																											"iOS 8.1 (iPhone)",
																																																																																											new String[] {
																																																																																													"iPhone OS 8_1" },
																																																																																											null,
																																																																																											DeviceType.MOBILE,
																																																																																											null), iOS8_IPHONE(
																																																																																													Manufacturer.APPLE,
																																																																																													IOS,
																																																																																													45,
																																																																																													"iOS 8 (iPhone)",
																																																																																													new String[] {
																																																																																															"iPhone OS 8" },
																																																																																													null,
																																																																																													DeviceType.MOBILE,
																																																																																													null), iOS7_IPHONE(
																																																																																															Manufacturer.APPLE,
																																																																																															IOS,
																																																																																															44,
																																																																																															"iOS 7 (iPhone)",
																																																																																															new String[] {
																																																																																																	"iPhone OS 7" },
																																																																																															null,
																																																																																															DeviceType.MOBILE,
																																																																																															null), iOS6_IPHONE(
																																																																																																	Manufacturer.APPLE,
																																																																																																	IOS,
																																																																																																	43,
																																																																																																	"iOS 6 (iPhone)",
																																																																																																	new String[] {
																																																																																																			"iPhone OS 6" },
																																																																																																	null,
																																																																																																	DeviceType.MOBILE,
																																																																																																	null), iOS5_IPHONE(
																																																																																																			Manufacturer.APPLE,
																																																																																																			IOS,
																																																																																																			42,
																																																																																																			"iOS 5 (iPhone)",
																																																																																																			new String[] {
																																																																																																					"iPhone OS 5" },
																																																																																																			null,
																																																																																																			DeviceType.MOBILE,
																																																																																																			null), iOS4_IPHONE(
																																																																																																					Manufacturer.APPLE,
																																																																																																					IOS,
																																																																																																					41,
																																																																																																					"iOS 4 (iPhone)",
																																																																																																					new String[] {
																																																																																																							"iPhone OS 4" },
																																																																																																					null,
																																																																																																					DeviceType.MOBILE,
																																																																																																					null), MAC_OS_X_IPAD(
																																																																																																							Manufacturer.APPLE,
																																																																																																							IOS,
																																																																																																							50,
																																																																																																							"Mac OS X (iPad)",
																																																																																																							new String[] {
																																																																																																									"iPad" },
																																																																																																							null,
																																																																																																							DeviceType.TABLET,
																																																																																																							null), iOS11_IPAD(
																																																																																																									Manufacturer.APPLE,
																																																																																																									MAC_OS_X_IPAD,
																																																																																																									60,
																																																																																																									"iOS 11 (iPad)",
																																																																																																									new String[] {
																																																																																																											"OS 11" },
																																																																																																									null,
																																																																																																									DeviceType.TABLET,
																																																																																																									null), iOS10_IPAD(
																																																																																																											Manufacturer.APPLE,
																																																																																																											MAC_OS_X_IPAD,
																																																																																																											59,
																																																																																																											"iOS 10 (iPad)",
																																																																																																											new String[] {
																																																																																																													"OS 10" },
																																																																																																											null,
																																																																																																											DeviceType.TABLET,
																																																																																																											null), iOS9_IPAD(
																																																																																																													Manufacturer.APPLE,
																																																																																																													MAC_OS_X_IPAD,
																																																																																																													58,
																																																																																																													"iOS 9 (iPad)",
																																																																																																													new String[] {
																																																																																																															"OS 9" },
																																																																																																													null,
																																																																																																													DeviceType.TABLET,
																																																																																																													null), iOS8_4_IPAD(
																																																																																																															Manufacturer.APPLE,
																																																																																																															MAC_OS_X_IPAD,
																																																																																																															57,
																																																																																																															"iOS 8.4 (iPad)",
																																																																																																															new String[] {
																																																																																																																	"OS 8_4" },
																																																																																																															null,
																																																																																																															DeviceType.TABLET,
																																																																																																															null), iOS8_3_IPAD(
																																																																																																																	Manufacturer.APPLE,
																																																																																																																	MAC_OS_X_IPAD,
																																																																																																																	56,
																																																																																																																	"iOS 8.3 (iPad)",
																																																																																																																	new String[] {
																																																																																																																			"OS 8_3" },
																																																																																																																	null,
																																																																																																																	DeviceType.TABLET,
																																																																																																																	null), iOS8_2_IPAD(
																																																																																																																			Manufacturer.APPLE,
																																																																																																																			MAC_OS_X_IPAD,
																																																																																																																			55,
																																																																																																																			"iOS 8.2 (iPad)",
																																																																																																																			new String[] {
																																																																																																																					"OS 8_2" },
																																																																																																																			null,
																																																																																																																			DeviceType.TABLET,
																																																																																																																			null), iOS8_1_IPAD(
																																																																																																																					Manufacturer.APPLE,
																																																																																																																					MAC_OS_X_IPAD,
																																																																																																																					54,
																																																																																																																					"iOS 8.1 (iPad)",
																																																																																																																					new String[] {
																																																																																																																							"OS 8_1" },
																																																																																																																					null,
																																																																																																																					DeviceType.TABLET,
																																																																																																																					null), iOS8_IPAD(
																																																																																																																							Manufacturer.APPLE,
																																																																																																																							MAC_OS_X_IPAD,
																																																																																																																							53,
																																																																																																																							"iOS 8 (iPad)",
																																																																																																																							new String[] {
																																																																																																																									"OS 8_0" },
																																																																																																																							null,
																																																																																																																							DeviceType.TABLET,
																																																																																																																							null), iOS7_IPAD(
																																																																																																																									Manufacturer.APPLE,
																																																																																																																									MAC_OS_X_IPAD,
																																																																																																																									52,
																																																																																																																									"iOS 7 (iPad)",
																																																																																																																									new String[] {
																																																																																																																											"OS 7" },
																																																																																																																									null,
																																																																																																																									DeviceType.TABLET,
																																																																																																																									null), iOS6_IPAD(
																																																																																																																											Manufacturer.APPLE,
																																																																																																																											MAC_OS_X_IPAD,
																																																																																																																											51,
																																																																																																																											"iOS 6 (iPad)",
																																																																																																																											new String[] {
																																																																																																																													"OS 6" },
																																																																																																																											null,
																																																																																																																											DeviceType.TABLET,
																																																																																																																											null), MAC_OS_X_IPHONE(
																																																																																																																													Manufacturer.APPLE,
																																																																																																																													IOS,
																																																																																																																													40,
																																																																																																																													"Mac OS X (iPhone)",
																																																																																																																													new String[] {
																																																																																																																															"iPhone" },
																																																																																																																													null,
																																																																																																																													DeviceType.MOBILE,
																																																																																																																													null), MAC_OS_X_IPOD(
																																																																																																																															Manufacturer.APPLE,
																																																																																																																															IOS,
																																																																																																																															30,
																																																																																																																															"Mac OS X (iPod)",
																																																																																																																															new String[] {
																																																																																																																																	"iPod" },
																																																																																																																															null,
																																																																																																																															DeviceType.MOBILE,
																																																																																																																															null), MAC_OS_X(
																																																																																																																																	Manufacturer.APPLE,
																																																																																																																																	null,
																																																																																																																																	10,
																																																																																																																																	"Mac OS X",
																																																																																																																																	new String[] {
																																																																																																																																			"Mac OS X",
																																																																																																																																			"CFNetwork" },
																																																																																																																																	null,
																																																																																																																																	DeviceType.COMPUTER,
																																																																																																																																	null), MAC_OS(
																																																																																																																																			Manufacturer.APPLE,
																																																																																																																																			null,
																																																																																																																																			1,
																																																																																																																																			"Mac OS",
																																																																																																																																			new String[] {
																																																																																																																																					"Mac" },
																																																																																																																																			null,
																																																																																																																																			DeviceType.COMPUTER,
																																																																																																																																			null), MAEMO(
																																																																																																																																					Manufacturer.NOKIA,
																																																																																																																																					null,
																																																																																																																																					2,
																																																																																																																																					"Maemo",
																																																																																																																																					new String[] {
																																																																																																																																							"Maemo" },
																																																																																																																																					null,
																																																																																																																																					DeviceType.MOBILE,
																																																																																																																																					null), BADA(
																																																																																																																																							Manufacturer.SAMSUNG,
																																																																																																																																							null,
																																																																																																																																							2,
																																																																																																																																							"Bada",
																																																																																																																																							new String[] {
																																																																																																																																									"Bada" },
																																																																																																																																							null,
																																																																																																																																							DeviceType.MOBILE,
																																																																																																																																							null), GOOGLE_TV(
																																																																																																																																									Manufacturer.GOOGLE,
																																																																																																																																									null,
																																																																																																																																									100,
																																																																																																																																									"Android (Google TV)",
																																																																																																																																									new String[] {
																																																																																																																																											"GoogleTV" },
																																																																																																																																									null,
																																																																																																																																									DeviceType.DMR,
																																																																																																																																									null), TIZEN(
																																																																																																																																											Manufacturer.LINUX_FOUNDATION,
																																																																																																																																											null,
																																																																																																																																											101,
																																																																																																																																											"Tizen",
																																																																																																																																											new String[] {
																																																																																																																																													"Tizen" },
																																																																																																																																											null,
																																																																																																																																											DeviceType.UNKNOWN,
																																																																																																																																											null), TIZEN3(
																																																																																																																																													Manufacturer.LINUX_FOUNDATION,
																																																																																																																																													TIZEN,
																																																																																																																																													30,
																																																																																																																																													"Tizen 3",
																																																																																																																																													new String[] {
																																																																																																																																															"Tizen 3." },
																																																																																																																																													null,
																																																																																																																																													DeviceType.UNKNOWN,
																																																																																																																																													null), TIZEN3_MOBILE(
																																																																																																																																															Manufacturer.LINUX_FOUNDATION,
																																																																																																																																															TIZEN3,
																																																																																																																																															31,
																																																																																																																																															"Tizen 3 (Mobile)",
																																																																																																																																															new String[] {
																																																																																																																																																	"mobile" },
																																																																																																																																															null,
																																																																																																																																															DeviceType.MOBILE,
																																																																																																																																															null), TIZEN3_TV(
																																																																																																																																																	Manufacturer.LINUX_FOUNDATION,
																																																																																																																																																	TIZEN3,
																																																																																																																																																	32,
																																																																																																																																																	"Tizen 3 (SmartTV)",
																																																																																																																																																	new String[] {
																																																																																																																																																			"Smart-TV",
																																																																																																																																																			" TV " },
																																																																																																																																																	null,
																																																																																																																																																	DeviceType.DMR,
																																																																																																																																																	null), TIZEN2(
																																																																																																																																																			Manufacturer.LINUX_FOUNDATION,
																																																																																																																																																			TIZEN,
																																																																																																																																																			20,
																																																																																																																																																			"Tizen 2",
																																																																																																																																																			new String[] {
																																																																																																																																																					"Tizen 2." },
																																																																																																																																																			null,
																																																																																																																																																			DeviceType.UNKNOWN,
																																																																																																																																																			null), TIZEN2_MOBILE(
																																																																																																																																																					Manufacturer.LINUX_FOUNDATION,
																																																																																																																																																					TIZEN2,
																																																																																																																																																					21,
																																																																																																																																																					"Tizen 2 (Mobile)",
																																																																																																																																																					new String[] {
																																																																																																																																																							"mobile" },
																																																																																																																																																					null,
																																																																																																																																																					DeviceType.MOBILE,
																																																																																																																																																					null), TIZEN2_TV(
																																																																																																																																																							Manufacturer.LINUX_FOUNDATION,
																																																																																																																																																							TIZEN2,
																																																																																																																																																							22,
																																																																																																																																																							"Tizen 2 (SmartTV)",
																																																																																																																																																							new String[] {
																																																																																																																																																									"Smart-TV",
																																																																																																																																																									" TV " },
																																																																																																																																																							null,
																																																																																																																																																							DeviceType.DMR,
																																																																																																																																																							null), TIZEN_MOBILE(
																																																																																																																																																									Manufacturer.LINUX_FOUNDATION,
																																																																																																																																																									TIZEN,
																																																																																																																																																									10,
																																																																																																																																																									"Tizen (mobile)",
																																																																																																																																																									new String[] {
																																																																																																																																																											"mobile" },
																																																																																																																																																									null,
																																																																																																																																																									DeviceType.MOBILE,
																																																																																																																																																									null), KINDLE(
																																																																																																																																																											Manufacturer.AMAZON,
																																																																																																																																																											null,
																																																																																																																																																											1,
																																																																																																																																																											"Linux (Kindle)",
																																																																																																																																																											new String[] {
																																																																																																																																																													"Kindle" },
																																																																																																																																																											null,
																																																																																																																																																											DeviceType.TABLET,
																																																																																																																																																											null), KINDLE3(
																																																																																																																																																													Manufacturer.AMAZON,
																																																																																																																																																													KINDLE,
																																																																																																																																																													30,
																																																																																																																																																													"Linux (Kindle 3)",
																																																																																																																																																													new String[] {
																																																																																																																																																															"Kindle/3" },
																																																																																																																																																													null,
																																																																																																																																																													DeviceType.TABLET,
																																																																																																																																																													null), KINDLE2(
																																																																																																																																																															Manufacturer.AMAZON,
																																																																																																																																																															KINDLE,
																																																																																																																																																															20,
																																																																																																																																																															"Linux (Kindle 2)",
																																																																																																																																																															new String[] {
																																																																																																																																																																	"Kindle/2" },
																																																																																																																																																															null,
																																																																																																																																																															DeviceType.TABLET,
																																																																																																																																																															null), LINUX(
																																																																																																																																																																	Manufacturer.OTHER,
																																																																																																																																																																	null,
																																																																																																																																																																	2,
																																																																																																																																																																	"Linux",
																																																																																																																																																																	new String[] {
																																																																																																																																																																			"Linux",
																																																																																																																																																																			"CamelHttpStream" },
																																																																																																																																																																	null,
																																																																																																																																																																	DeviceType.COMPUTER,
																																																																																																																																																																	null), UBUNTU(
																																																																																																																																																																			Manufacturer.CONONICAL,
																																																																																																																																																																			LINUX,
																																																																																																																																																																			1,
																																																																																																																																																																			"Ubuntu",
																																																																																																																																																																			new String[] {
																																																																																																																																																																					"ubuntu" },
																																																																																																																																																																			null,
																																																																																																																																																																			DeviceType.COMPUTER,
																																																																																																																																																																			null), UBUNTU_TOUCH_MOBILE(
																																																																																																																																																																					Manufacturer.CONONICAL,
																																																																																																																																																																					UBUNTU,
																																																																																																																																																																					200,
																																																																																																																																																																					"Ubuntu Touch (mobile)",
																																																																																																																																																																					new String[] {
																																																																																																																																																																							"mobile" },
																																																																																																																																																																					null,
																																																																																																																																																																					DeviceType.MOBILE,
																																																																																																																																																																					null), LINUX_SMART_TV(
																																																																																																																																																																							Manufacturer.OTHER,
																																																																																																																																																																							LINUX,
																																																																																																																																																																							21,
																																																																																																																																																																							"Linux (SmartTV)",
																																																																																																																																																																							new String[] {
																																																																																																																																																																									"SmartTv" },
																																																																																																																																																																							null,
																																																																																																																																																																							DeviceType.DMR,
																																																																																																																																																																							null), SYMBIAN(
																																																																																																																																																																									Manufacturer.SYMBIAN,
																																																																																																																																																																									null,
																																																																																																																																																																									1,
																																																																																																																																																																									"Symbian OS",
																																																																																																																																																																									new String[] {
																																																																																																																																																																											"Symbian",
																																																																																																																																																																											"Series60" },
																																																																																																																																																																									null,
																																																																																																																																																																									DeviceType.MOBILE,
																																																																																																																																																																									null), SYMBIAN9(
																																																																																																																																																																											Manufacturer.SYMBIAN,
																																																																																																																																																																											SYMBIAN,
																																																																																																																																																																											20,
																																																																																																																																																																											"Symbian OS 9.x",
																																																																																																																																																																											new String[] {
																																																																																																																																																																													"SymbianOS/9",
																																																																																																																																																																													"Series60/3" },
																																																																																																																																																																											null,
																																																																																																																																																																											DeviceType.MOBILE,
																																																																																																																																																																											null), SYMBIAN8(
																																																																																																																																																																													Manufacturer.SYMBIAN,
																																																																																																																																																																													SYMBIAN,
																																																																																																																																																																													15,
																																																																																																																																																																													"Symbian OS 8.x",
																																																																																																																																																																													new String[] {
																																																																																																																																																																															"SymbianOS/8",
																																																																																																																																																																															"Series60/2.6",
																																																																																																																																																																															"Series60/2.8" },
																																																																																																																																																																													null,
																																																																																																																																																																													DeviceType.MOBILE,
																																																																																																																																																																													null), SYMBIAN7(
																																																																																																																																																																															Manufacturer.SYMBIAN,
																																																																																																																																																																															SYMBIAN,
																																																																																																																																																																															10,
																																																																																																																																																																															"Symbian OS 7.x",
																																																																																																																																																																															new String[] {
																																																																																																																																																																																	"SymbianOS/7" },
																																																																																																																																																																															null,
																																																																																																																																																																															DeviceType.MOBILE,
																																																																																																																																																																															null), SYMBIAN6(
																																																																																																																																																																																	Manufacturer.SYMBIAN,
																																																																																																																																																																																	SYMBIAN,
																																																																																																																																																																																	5,
																																																																																																																																																																																	"Symbian OS 6.x",
																																																																																																																																																																																	new String[] {
																																																																																																																																																																																			"SymbianOS/6" },
																																																																																																																																																																																	null,
																																																																																																																																																																																	DeviceType.MOBILE,
																																																																																																																																																																																	null), SERIES40(
																																																																																																																																																																																			Manufacturer.NOKIA,
																																																																																																																																																																																			null,
																																																																																																																																																																																			1,
																																																																																																																																																																																			"Series 40",
																																																																																																																																																																																			new String[] {
																																																																																																																																																																																					"Nokia6300" },
																																																																																																																																																																																			null,
																																																																																																																																																																																			DeviceType.MOBILE,
																																																																																																																																																																																			null), SONY_ERICSSON(
																																																																																																																																																																																					Manufacturer.SONY_ERICSSON,
																																																																																																																																																																																					null,
																																																																																																																																																																																					1,
																																																																																																																																																																																					"Sony Ericsson",
																																																																																																																																																																																					new String[] {
																																																																																																																																																																																							"SonyEricsson" },
																																																																																																																																																																																					null,
																																																																																																																																																																																					DeviceType.MOBILE,
																																																																																																																																																																																					null), SUN_OS(
																																																																																																																																																																																							Manufacturer.SUN,
																																																																																																																																																																																							null,
																																																																																																																																																																																							1,
																																																																																																																																																																																							"SunOS",
																																																																																																																																																																																							new String[] {
																																																																																																																																																																																									"SunOS" },
																																																																																																																																																																																							null,
																																																																																																																																																																																							DeviceType.COMPUTER,
																																																																																																																																																																																							null), PSP(
																																																																																																																																																																																									Manufacturer.SONY,
																																																																																																																																																																																									null,
																																																																																																																																																																																									1,
																																																																																																																																																																																									"Sony Playstation",
																																																																																																																																																																																									new String[] {
																																																																																																																																																																																											"Playstation" },
																																																																																																																																																																																									null,
																																																																																																																																																																																									DeviceType.GAME_CONSOLE,
																																																																																																																																																																																									null), WII(
																																																																																																																																																																																											Manufacturer.NINTENDO,
																																																																																																																																																																																											null,
																																																																																																																																																																																											1,
																																																																																																																																																																																											"Nintendo Wii",
																																																																																																																																																																																											new String[] {
																																																																																																																																																																																													"Wii" },
																																																																																																																																																																																											null,
																																																																																																																																																																																											DeviceType.GAME_CONSOLE,
																																																																																																																																																																																											null), BLACKBERRY(
																																																																																																																																																																																													Manufacturer.BLACKBERRY,
																																																																																																																																																																																													null,
																																																																																																																																																																																													1,
																																																																																																																																																																																													"BlackBerryOS",
																																																																																																																																																																																													new String[] {
																																																																																																																																																																																															"BlackBerry" },
																																																																																																																																																																																													null,
																																																																																																																																																																																													DeviceType.MOBILE,
																																																																																																																																																																																													null), BLACKBERRY7(
																																																																																																																																																																																															Manufacturer.BLACKBERRY,
																																																																																																																																																																																															BLACKBERRY,
																																																																																																																																																																																															7,
																																																																																																																																																																																															"BlackBerry 7",
																																																																																																																																																																																															new String[] {
																																																																																																																																																																																																	"Version/7" },
																																																																																																																																																																																															null,
																																																																																																																																																																																															DeviceType.MOBILE,
																																																																																																																																																																																															null), BLACKBERRY6(
																																																																																																																																																																																																	Manufacturer.BLACKBERRY,
																																																																																																																																																																																																	BLACKBERRY,
																																																																																																																																																																																																	6,
																																																																																																																																																																																																	"BlackBerry 6",
																																																																																																																																																																																																	new String[] {
																																																																																																																																																																																																			"Version/6" },
																																																																																																																																																																																																	null,
																																																																																																																																																																																																	DeviceType.MOBILE,
																																																																																																																																																																																																	null), BLACKBERRY_TABLET(
																																																																																																																																																																																																			Manufacturer.BLACKBERRY,
																																																																																																																																																																																																			null,
																																																																																																																																																																																																			100,
																																																																																																																																																																																																			"BlackBerry Tablet OS",
																																																																																																																																																																																																			new String[] {
																																																																																																																																																																																																					"RIM Tablet OS" },
																																																																																																																																																																																																			null,
																																																																																																																																																																																																			DeviceType.TABLET,
																																																																																																																																																																																																			null), ROKU(
																																																																																																																																																																																																					Manufacturer.ROKU,
																																																																																																																																																																																																					null,
																																																																																																																																																																																																					1,
																																																																																																																																																																																																					"Roku OS",
																																																																																																																																																																																																					new String[] {
																																																																																																																																																																																																							"Roku" },
																																																																																																																																																																																																					null,
																																																																																																																																																																																																					DeviceType.DMR,
																																																																																																																																																																																																					null), PROXY(
																																																																																																																																																																																																							Manufacturer.OTHER,
																																																																																																																																																																																																							null,
																																																																																																																																																																																																							10,
																																																																																																																																																																																																							"Proxy",
																																																																																																																																																																																																							new String[] {
																																																																																																																																																																																																									"ggpht.com" },
																																																																																																																																																																																																							null,
																																																																																																																																																																																																							DeviceType.UNKNOWN,
																																																																																																																																																																																																							null), UNKNOWN_MOBILE(
																																																																																																																																																																																																									Manufacturer.OTHER,
																																																																																																																																																																																																									null,
																																																																																																																																																																																																									3,
																																																																																																																																																																																																									"Unknown mobile",
																																																																																																																																																																																																									new String[] {
																																																																																																																																																																																																											"Mobile" },
																																																																																																																																																																																																									null,
																																																																																																																																																																																																									DeviceType.MOBILE,
																																																																																																																																																																																																									null), UNKNOWN_TABLET(
																																																																																																																																																																																																											Manufacturer.OTHER,
																																																																																																																																																																																																											null,
																																																																																																																																																																																																											4,
																																																																																																																																																																																																											"Unknown tablet",
																																																																																																																																																																																																											new String[] {
																																																																																																																																																																																																													"Tablet" },
																																																																																																																																																																																																											null,
																																																																																																																																																																																																											DeviceType.TABLET,
																																																																																																																																																																																																											null), UNKNOWN(
																																																																																																																																																																																																													Manufacturer.OTHER,
																																																																																																																																																																																																													null,
																																																																																																																																																																																																													1,
																																																																																																																																																																																																													"Unknown",
																																																																																																																																																																																																													new String[0],
																																																																																																																																																																																																													null,
																																																																																																																																																																																																													DeviceType.UNKNOWN,
																																																																																																																																																																																																													null);

	private final short id;

	private final String name;

	private final String[] aliases;

	private final String[] excludeList;

	private final Manufacturer manufacturer;

	private final DeviceType deviceType;

	private final OperatingSystem parent;

	private List<OperatingSystem> children;

	private Pattern versionRegEx;

	private static List<OperatingSystem> topLevelOperatingSystems;

	OperatingSystem(Manufacturer manufacturer, OperatingSystem parent, int versionId, String name, String[] aliases,
			String[] exclude, DeviceType deviceType, String versionRegexString) {
		this.manufacturer = manufacturer;
		this.parent = parent;
		this.children = new ArrayList<>();
		this.id = (short) ((manufacturer.getId() << 8) + ((byte) versionId & 0xff));
		this.name = name;
		this.aliases = StringUtil.toLowerCase(aliases);
		this.excludeList = StringUtil.toLowerCase(exclude);
		this.deviceType = deviceType;
		if (versionRegexString != null) {
			this.versionRegEx = Pattern.compile(versionRegexString);
		}
		if (this.parent == null) {
			addTopLevelOperatingSystem(this);
		}
		else {
			this.parent.children.add(this);
		}
	}

	private static void addTopLevelOperatingSystem(OperatingSystem os) {
		if (topLevelOperatingSystems == null) {
			topLevelOperatingSystems = new ArrayList<>();
		}
		topLevelOperatingSystems.add(os);
	}

	public short getId() {
		return this.id;
	}

	public String getName() {
		return this.name;
	}

	public boolean isMobileDevice() {
		return this.deviceType.equals(DeviceType.MOBILE);
	}

	public DeviceType getDeviceType() {
		return this.deviceType;
	}

	public OperatingSystem getGroup() {
		if (this.parent != null) {
			return this.parent.getGroup();
		}
		return this;
	}

	public Manufacturer getManufacturer() {
		return this.manufacturer;
	}

	public boolean isInUserAgentString(String agentString) {
		if (agentString == null) {
			return false;
		}
		String agentLowerCaseString = agentString.toLowerCase();
		return isInUserAgentStringLowercase(agentLowerCaseString);
	}

	private boolean isInUserAgentStringLowercase(String agentLowerCaseString) {
		return StringUtil.contains(agentLowerCaseString, this.aliases);
	}

	private boolean containsExcludeTokenLowercase(String agentLowerCaseString) {
		return StringUtil.contains(agentLowerCaseString, this.excludeList);
	}

	private OperatingSystem checkUserAgentLowercase(String agentStringLowercase) {
		if (isInUserAgentStringLowercase(agentStringLowercase)) {
			if (!this.children.isEmpty()) {
				for (OperatingSystem childOperatingSystem : this.children) {
					OperatingSystem match = childOperatingSystem.checkUserAgentLowercase(agentStringLowercase);
					if (match != null) {
						return match;
					}
				}
			}
			if (!containsExcludeTokenLowercase(agentStringLowercase)) {
				return this;
			}
		}
		return null;
	}

	public static OperatingSystem parseUserAgentString(String agentString) {
		return parseUserAgentString(agentString, topLevelOperatingSystems);
	}

	public static OperatingSystem parseUserAgentLowercaseString(String agentString) {
		if (agentString == null) {
			return UNKNOWN;
		}
		return parseUserAgentLowercaseString(agentString, topLevelOperatingSystems);
	}

	public static OperatingSystem parseUserAgentString(String agentString, List<OperatingSystem> operatingSystems) {
		if (agentString != null) {
			String agentLowercaseString = agentString.toLowerCase();
			return parseUserAgentLowercaseString(agentLowercaseString, operatingSystems);
		}
		return UNKNOWN;
	}

	private static OperatingSystem parseUserAgentLowercaseString(String agentLowercaseString,
			List<OperatingSystem> operatingSystems) {
		for (OperatingSystem operatingSystem : operatingSystems) {
			OperatingSystem match = operatingSystem.checkUserAgentLowercase(agentLowercaseString);
			if (match != null) {
				return match;
			}
		}
		return UNKNOWN;
	}

}
